package gov.tax.rti.base.service.impl;

import gov.tax.rti.base.jdbc.impl.DataMapJdbcImpl;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.bstek.dorado.core.el.ExpressionHandler;
import com.bstek.dorado.web.DoradoContext;

@Service
public class DataMapServiceImpl {
	
	@Resource
	private DataMapJdbcImpl dataMapJdbcImpl;

	@SuppressWarnings("unchecked")
	public List<Map<Object, Object>> getMapping(String sqlKey) {
		String mapValue = sqlKey;
		Map<String, Object> mapSqls = dataMapJdbcImpl.getMapSqls(sqlKey);
		if(mapSqls!=null && !mapSqls.isEmpty()){
			mapValue = (String)mapSqls.get("MAPVALUE");
		}
		List<Map<Object,Object>> mapping = null;//new ArrayList<Map<String,Object>>();
		if(StringUtils.isNotEmpty(mapValue)){
			if(mapValue.startsWith("Table:")){
				String dataSource = (String)mapSqls.get("DATASOURCE");
				mapping = getTableMapValues(mapValue.substring("Table:".length()), dataSource);
			}else if(mapValue.startsWith("Sql:")){
				String dataSource = (String)mapSqls.get("DATASOURCE");
				mapping = getSqlMapValues(mapValue.substring("Sql:".length()), dataSource);
			}else if(mapValue.startsWith("Map:")){
				mapping = getMapMapValues(mapValue.substring("Map:".length()));
			}else{
				try {
					ExpressionHandler expressionHandler = (ExpressionHandler) DoradoContext.getCurrent().getServiceBean("expressionHandler");
					mapping = (List<Map<Object, Object>>) expressionHandler.compile(mapValue).evaluate();
				} catch (Exception e) {
					//TODO log
					return null;
				}
			}
		}
		return mapping;
	}
	
	@SuppressWarnings("unchecked")
	public List<Map<Object, Object>> getJoinMapping(String sqlKey,Map<String,Object> paras) {
		String mapValue = sqlKey;
		Map<String, Object> mapSqls = dataMapJdbcImpl.getMapSqls(sqlKey);
		if(mapSqls!=null && !mapSqls.isEmpty()){
			mapValue = (String)mapSqls.get("JOINVALUE");
		}
		List<Map<Object,Object>> mapping = null;//new ArrayList<Map<String,Object>>();
		if(StringUtils.isNotEmpty(mapValue)){
			if(mapValue.startsWith("Sql:")){
				String dataSource = (String)mapSqls.get("DATASOURCE");
				mapping = getSqlMapValues(mapValue.substring("Sql:".length()),paras, dataSource);
			}else{
				try {
					ExpressionHandler expressionHandler = (ExpressionHandler) DoradoContext.getCurrent().getServiceBean("expressionHandler");
					mapping = (List<Map<Object, Object>>) expressionHandler.compile(mapValue).evaluate();
				} catch (Exception e) {
					//TODO log
					return null;
				}
			}
		}
		return mapping;
	}
	
	private List<Map<Object, Object>> getMapMapValues(String mapValue) {
		List<Map<Object, Object>> mapping = null;
		String strs[] = StringUtils.split(mapValue, ';');
		if(strs != null && strs.length > 0){
			mapping = new ArrayList<Map<Object,Object>>();
			for (String str : strs) {
				if(StringUtils.isNotEmpty(str)){
					String strCs[] = StringUtils.split(str, ',');
					if(strCs.length == 2){
						Map<Object, Object> data = new LinkedHashMap<Object, Object>();
						data.put("key", strCs[0]);
						data.put("value", strCs[1]);
						mapping.add(data);
					}else{
						//TODO Log Warn or throw Exception
					}
				}
			}
		}
		return mapping;
	}
	
	private List<Map<Object, Object>> getTableMapValues(String mapValue, String dataSource) {
		List<Map<Object,Object>> mapping = null;
		String strs[] = StringUtils.split(mapValue, ';');
		if(strs != null && strs.length >= 3 && strs.length <= 4){
			String table = strs[0];
			String keyColumn = strs[1];
			String valueColumn = strs[2];
			String orderBy = "";
			if(strs.length == 4){
				orderBy = strs[3];
			}
			String sql = "select " +keyColumn+','+valueColumn + " from "+ table;
			if(StringUtils.isNotEmpty(orderBy)){
				sql += " order by " + orderBy;
			}
			return getSqlMapValues(sql, dataSource);
		}else{
			//TODO Log Warn
		}
		return mapping;
	}
	
	private List<Map<Object, Object>> getSqlMapValues(String sql, String dataSource) {
		return dataMapJdbcImpl.getSqlMapping(sql, dataSource);
	}
	
	private List<Map<Object, Object>> getSqlMapValues(String sql,Map<String,Object> paras, String dataSource) {
		return dataMapJdbcImpl.getSqlMapping(sql, paras, dataSource);
	}

}
